package com.wbk.lotterysystemgateway.filter;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

@Slf4j
public class WxBizDataCryptUtil {

    /**
     * 算法名
     */
    public static final String KEY_NAME = "AES";
    /**
     * 加解密算法/模式/填充方式
     * ECB模式只用密钥即可对数据进行加密解密，CBC模式需要添加一个iv
     */
    public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    /**
     * 1.对称解密使用的算法为 AES-128-CBC，数据采用PKCS#7填充。
     * 2.对称解密的目标密文为 Base64_Decode(encryptedData)。
     * 3.对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
     * 4.对称解密算法初始向量 为Base64_Decode(iv)，其中iv由数据接口返回。
     *
     * @param encryptedData
     * @param iv
     * @param sessionKey
     * @return
     */
    public static JSONObject decryptData(String encryptedData, String iv, String sessionKey) {
        String json = null;
        byte[] encrypted64 = Base64.decodeBase64(encryptedData);
        byte[] key64 = Base64.decodeBase64(sessionKey);
        byte[] iv64 = Base64.decodeBase64(iv);
        try {
            init();
            json = new String(decrypt(encrypted64, key64, generateIv(iv64)));
            log.info(String.format(">>>> %s wxDecrypt 数据解析结果:%s", System.currentTimeMillis(), json));
        } catch (Exception e) {
            log.error("解密微信失败:" + e.getMessage(), e);
        }
        return JSONObject.parseObject(json);
    }

    /**
     * 初始化密钥
     */
    public static void init() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        KeyGenerator.getInstance(KEY_NAME).init(128);
    }

    /**
     * 生成iv
     */
    public static AlgorithmParameters generateIv(byte[] iv) throws Exception {
        // iv 为一个 16 字节的数组，这里采用和 iOS 端一样的构造方法，数据全为0
        AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
        params.init(new IvParameterSpec(iv));
        return params;
    }

    /**
     * 生成解密
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
            throws Exception {
        Key key = new SecretKeySpec(keyBytes, KEY_NAME);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // 设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(encryptedData);
    }

    public static JSONObject stepInfo(String encryptedData, String sessionKey, String iv) {
        String json = null;
        byte[] encrypted64 = Base64.decodeBase64(encryptedData);
        byte[] key64 = Base64.decodeBase64(sessionKey);
        byte[] iv64 = Base64.decodeBase64(iv);
        try {
            init();
            json = new String(decrypt(encrypted64, key64, generateIv(iv64)));
        } catch (Exception e) {
            log.error("解密失败:{}", e.getMessage());
        }
        JSONObject jsonObject = JSONObject.parseObject(json);
        if (jsonObject == null) {
            return null;
        }
        log.info("解密结果:{}", jsonObject.toJSONString());
        return jsonObject;
    }

    public static void main(String[] args) {
        String json = null;
//        String sessionKey = "qFitG9Wdt+qFi1//twh6/w==";
//        String iv = "9gejFMBw0jbXX09Pv2vnlg==";
//        String encryptedData = "YGek62ndAPLhB9g+U2vPbKveaH2Z3xBO1seqdYyuCjdFydjLJC3r33O3KxWLJ94yofQhyRy457FcytepyYXcZDopqJQ+2cblwMaTHiH9lC5So7BU92uvtIpdqw0yOGyKAp2qKIRZzLcEOhqKSkdtn0xEAftv6EMIw0xMDvvuKfM9mtXz4Ic91UhFhESztt5uAzPOoDb+ULLAB4IoedCLIIeoG/yoeDeTvGvM0Hw8RuZpqkMDFPRLZQSVXEosFXwI86DYaplMECl+cnJ6AiuMAFfwA5Xi9kBhRG29JHyw7NQ7Ky481xF61WwFa1Z8Bp8oGUCWvlKPmpK+2F4I/JtoAgXbg8HFtLuW+m193aKH63INvTMQtZAtEDqyXBuy2UU9mT5dzIIcHy5sEd7Yk4ZViwfhUV10iz8Zw8IUUucZglF93qk3nqmNhplQNBHnQZyOeztzMu9RSAdEVbaYxdxmDZe8J3YuCy9z1JO0hWd4OGqSdkEBJG9kO6s7y1h4l8Ua+hXEzGp6FmJiFuXy2W15BZ4aHJeScawwPRQGIs1A5ygJgxfPUNlGVLgqMd7ulLzIl1r20BPed3eU02FKgaA20TvCZOzdaXGLMXSvSnj8MMzMMPAnihVyxMgLG7mF+kb3OviGEiIvkUzeROUm+wpjZgnlG55QpCIxcIfVuPimUSlGkTKISpbGfS65hOoJuUgyI2MmJ7ZY06hqL3HUJ1cZUWK7EUkrvnEr32vk+E4ELavz1/fSCfdUHNMplc6sXD9L3qwIeGq5JJtkPv5dCxtROa61LSQnoBfoFedp/2jRkvFAAVTDS4SHrOQASestXeGGQyweZxPaYiR365/ixuJZFyRMUUpeqwKX2wzt6hsiSUsGIOmMfT0Uec7ORFCGhNmDZdgYZBQLQxVbvlQEKZ4xxAP2t5HHSW35W9AmkIzriPPBj0uIQmDkjsPMH+suL1bHU4NvgthRoj+4jLjKx+5VBt4GA+WEWU0R6QPpHKVIvqDcRfEfCUSlBOg64spLrmWwNHQ2fSDUy468We9gcJUfBzrXlfPwDjEvyvFdSIBE9rxZxSprp1nLnsIkCE8aZt5XQyqqkd9X4qM86JcCw9m6PxOI1MO3v2Dy8MEarIR99NSGPBopJy6NhRoyd+jyPq14AvGmnbYRcVaHfxjoIdo/Bzqdqyhe9W1G2hxF2y7zofDTxljhjABBsIKem3zNq9HV8LcTVUOtQEh6p/MRSYOvo2e6xIl+hyBY1sjS+vlLNaMo4S1VkNapTY0uioxBmHpxIwMR+hb2gBPfEI1QNEG6EkTSePhLQ3jTnUajKBWugSUIWdlQcrHAaxNghXkuL7+IyJZzuN0Nuip0v7kQ8kTT40TbVAccGQfPbR/h7SekvTE3tBu2OtYJnm9CW671gEh+db6jrU0qSRm+Pudrr2m+pvLY2ytknG/Ig7hCqRQadneaTyfopqSegAqAIEgT0W6QcVwvGBh+lopyHcLd76c+zg8Zn0jhWPHjKeKD4EdYhXf26qeuj/xZYnlGWiINgNBJA5rxqfdyHgP7MGtNJ1B2Xk7Ae9MMYJj/pkCP2cz/07ZOdmHy5ENAkgZGqyTOMkS5nW9oeaUH46jejTGJ3YOM+BE7a72F7vy/K8siCjbJOMYLO9UfHhBbkpet9a+++pD/";

        String sessionKey = "tiihtNczf5v6AKRyjwEUhQ==";
        String iv = "r7BXXKkLb8qrSNn05n0qiA==";
        String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==";
        byte[] encrypted64 = Base64.decodeBase64(encryptedData);
        byte[] key64 = Base64.decodeBase64(sessionKey);
        byte[] iv64 = Base64.decodeBase64(iv);
        try {
            init();
            json = new String(decrypt(encrypted64, key64, generateIv(iv64)));
        } catch (Exception e) {
            log.error("解密失败:{}", e.getMessage());
        }
        JSONObject jsonObject = JSONObject.parseObject(json);
        System.out.println(jsonObject);
    }

}
